
This table gives an overview of data sizes a chunk span represents, depending on the level of recursion.

\begin{table}[ht]
\begin{tabular}{|r||r|r|r||r|r|r|}
\hline
&\multicolumn{6}{|c|}{span}\\\hline
&\multicolumn{3}{|c|}{unencrypted}
&\multicolumn{3}{|c|}{encrypted}\\\hline
level & chunks & $\mathit{log}_2$ of bytes & standard & chunks & $\mathit{log}_2$ of bytes & standard \\
\hline\hline
0 & 1 & 12 & 4KB & 1 & 12 & 4KB \\\hline
1 & 128 & 19 & 512KB & 64 & 18 & 256KB \\\hline
2 & 16,384 & 26 & 67MB & 4,096 & 24 & 16MB \\\hline
3 & 2,097,152 &33 & 8.5GB & 262,144 &  30 & 1.07GB\\\hline
4 & 268.44M & 40  & 1.1TB & 16.78M & 36 & 68.7GB\\\hline
5 & 34,359.74M & 47 & 140TB & 1,073.74M & 42  & 4.4TB\\\hline
\end{tabular}
\caption{Size of chunk spans}
\end{table}




\subsubsection{Calculating the Swarm Hash}

Client-side custom redundancy is achieved by CRS erasure coding (see \ref{sec:erasure} and \ref{sec:features}); using it neccessitates some CRS parameters.
      
\begin{definition}[File API: upload/storage;  swarm hash]\label{def:swarm-hash}
\begin{lstlisting}[language=buzz1]
// /file

define function encode @levels []chunk stream 
    for @level uint
as
    @chunks = @levels at @level     // read chunk stream 
    @crs = context crs              // 
    @m = branches (- @crs parities if @crs) 
    
    @parent = read @m from @chunks  // read up to m chunks from stream blocking
        (append crs/extend with @crs parities if @crs)
            each chunk/store        // package children reference
                join as chunk
                
    if @levels length == @level+1 then
        @levels append= stream{}
        go self @levels for @level+1
    
    write @parent to @levels at @level+1 
    if no @chunks then
        close @levels at @level + 1
    else
        self @chunks for @level
            
define function split @data byte stream 
as
    @level = chunk stream{}
    go @data each chunk size as chunk 
        write to @chunks
    @level

define function upload byte stream as @data
has api POST  on "file/" from @data as body
as
    @levels append= @data split     // 
    go encode @levels for 0
    @top = @levels each wait for  // wait for all levels to close
    return @top at 0              // return root hash as address        
\end{lstlisting}
\end{definition}
                   

\begin{definition}[File   API: download/retrieval]\label{def:file-retrieval}
\begin{lstlisting}[language=buzz1]
// /file

define function copy to @reader stream of byte{}
    from @chunks stream of []chunk
    using @buffers stream of [@buffer.size]stream of [branches]chunk
as
    @chunks = read @buffers if no @chunks
    @chunk = read @chunks
    if no @chunk
        write @chunks to @buffer
        self @reader using @buffers
    write @chunk data to @reader

define function download reference
    ?using @buffer.size uint64
has api GET  on "file/<reference>" 
as
    @reader = stream of byte{} 
    @buffers = stream of [@buffer.size]stream of [branches]chunk
    chunk/retrieve @reference            // root chunk retrieval
        go decode into @buffer down to 1 // traverse          
    copy into @reader from @buffers 

define function decode chunk 
    into @response chunk stream
    ?down to @limit uint8
as
     
    @crs = context crs
    @all = @m = branches 
    if @crs then
        @m -= @crs parities
        if @crs strategy is not "race" then 
            @all = @m 
        
    @chunks = @chunk segments up to @all 
        each go as reference retrieve 
    wait for @m in @chunks 
    
    if @crs then 
        cancel @chunks
        @chunks = @chunks crs/repair with @crs parities 
    
    if @chunk span < chunk size exp @limit + 1 then
        @chunks each  into @reader
        
       
    @chunks each go self down to @limit  

\end{lstlisting}
\end{definition}


\begin{definition}[File info]\label{def:file-info}
\begin{lstlisting}[language=buzz1]
// /file

define type info
    mode        int64 
    size        int64
    modified    time        

\end{lstlisting}
\end{definition}
